package com.cfweb.api;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpSession;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import com.cfweb.controller.LoginHandler;
import com.cfweb.dao.CfUserMapper;
import com.cfweb.exception.CloudFoundryApiException;
import com.cfweb.util.CloudFoundryClientUtil;
import com.cfweb.util.HttpStatusUtil;
import com.cfweb.util.JsonUtil;
import com.cfweb.util.StringUtil;

public class UserApi {
	
	static Logger logger = Logger.getLogger(UserApi.class);
	
	@Autowired
	private CfUserMapper cuMapper;
	
	static Map<String,String> roleMap = new HashMap<String,String>();
	static {
		roleMap.put("OrgManager", "managers");
		roleMap.put("BillingManager", "billing_managers");
		roleMap.put("OrgAuditor", "auditors");
		roleMap.put("SpaceManager", "managers");
		roleMap.put("SpaceDeveloper", "developers");
		roleMap.put("SpaceAuditor", "auditors");
	}
	
	/**
	 * create a new user
	 * 
	 * @param session
	 * @param userName
	 * @param password
	 * @return boolean
	 * @throws Exception 
	 */
	public static boolean create_user(HttpSession session,
			final String userName, final String password) throws Exception {
		HttpClient httpClient = null;
		HttpPost httpPost = null;
		String userId;
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = "http://uaa" + host.substring(10) + "/Users";
			
			httpClient =  new DefaultHttpClient();
			httpPost = new HttpPost(urlPath);
			CloudFoundryClientUtil.setUuaHeaders(httpPost, session);
			String tmp = "{\"userName\":\"" + userName 
					+ "\",\"emails\":[{\"value\":\"" + userName  
					+ "\"}],\"password\":\"" + password  
					+ "\",\"name\":{\"givenName\":\"" + userName  
					+ "\",\"familyName\":\"" + userName + "\"}}";
			HttpEntity postEntity = new StringEntity(tmp, "UTF-8");
			httpPost.setEntity(postEntity);
			HttpResponse response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();  
			String content = EntityUtils.toString(entity, "UTF-8"); 
			Map<String, Object> data = JsonUtil.convertJsonToMap(content);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())&&response.getStatusLine().getStatusCode()!=200){	
				throw new CloudFoundryApiException(Integer.valueOf(response.getStatusLine().getStatusCode()),(String)data.get("message"));
			}		
			userId = (String) data.get("id");
			//String content = EntityUtils.toString(returnEntity, "UTF-8"); 
		} catch (Exception e) {
			throw e;
		} finally {
	        httpPost.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/users";
			
			httpClient =  new DefaultHttpClient();
			httpPost = new HttpPost(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpPost, session);
			String tmp = "{\"guid\":\"" + userId + "\"}";
			HttpEntity postEntity = new StringEntity(tmp, "UTF-8");
			httpPost.setEntity(postEntity);
			HttpResponse response = httpClient.execute(httpPost);	
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				String content = EntityUtils.toString(response.getEntity(), "UTF-8"); 
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException(Integer.valueOf(response.getStatusLine().getStatusCode()),(String)data.get("message"));
			}
			//String content = EntityUtils.toString(returnEntity, "UTF-8"); 
		} catch (Exception e) {
			delete_cc_user(session, userName);
			throw e;
		} finally {
	        httpPost.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		return true;
	}
	
	/**
     * delete a user
     * 
     * @param session
     * @param userName
     * @return boolean
     * @throws Exception 
     */
	public static boolean delete_user(HttpSession session, String userName) throws Exception{
		HttpClient httpClient = null;
		HttpDelete httpDelete = null;
		String userId;
		userId = get_user_id(session, userName);
		if (userId.isEmpty()) {
			return false;
		}
		delete_cc_user(session, userName);
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = "http://uaa" + host.substring(10) + "/Users/" + userId;
			
			httpClient =  new DefaultHttpClient();
			httpDelete = new HttpDelete(urlPath);
			CloudFoundryClientUtil.setUuaHeaders(httpDelete, session);
			HttpResponse response = httpClient.execute(httpDelete);	
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				String content = EntityUtils.toString(response.getEntity(), "UTF-8"); 
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException(Integer.valueOf(response.getStatusLine().getStatusCode()),(String)data.get("message"));
			}
		} catch (Exception e) {
			throw e;
		} finally {
			httpDelete.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		return true;
	}
	
	/**
     * delete a user of cc
     * 
     * @param session
     * @param userName
     * @return boolean
     * @throws Exception 
     */
	public static boolean delete_cc_user(HttpSession session, String userName) throws Exception{
		HttpClient httpClient = null;
		HttpDelete httpDelete = null;
		String userId;
		userId = get_user_id(session, userName);
		if (userId.isEmpty()) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/users/" + userId + "?async=false";
			
			httpClient =  new DefaultHttpClient();
			httpDelete = new HttpDelete(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpDelete, session);
			HttpResponse response = httpClient.execute(httpDelete);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				HttpEntity entity = response.getEntity();  
				String content = EntityUtils.toString(entity, "UTF-8"); 
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException((Integer)data.get("code"),(String)data.get("description"));
			} 
		} catch (Exception e) {
			throw e;
		} finally {
			httpDelete.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		return true;
	}
	
	/**
     * set roles of the user in the org
     * 
     * @param session
     * @param userName
     * @param orgName
     * @param roleType
     * @return boolean
     * @throws Exception 
     */
	public static boolean set_org_role(HttpSession session, String userName,
			String orgName, String roleType) throws Exception {
		HttpClient httpClient = null;
		HttpPut httpPut = null;
		String userId;
		String orgId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/organizations/" + orgId + "/" + roleMap.get(roleType)
					+ "/" + userId;
			
			httpClient =  new DefaultHttpClient();
			httpPut = new HttpPut(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpPut, session);
			HttpResponse response = httpClient.execute(httpPut);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				HttpEntity entity = response.getEntity();  
				String content = EntityUtils.toString(entity, "UTF-8"); 
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			} 
			add_into_org(session, userName, orgName);
		} catch (Exception e) {
			throw e;
		} finally {
			httpPut.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		return true;
	}
	
	/**
     * unset roles of the user in the org
     * 
     * @param session
     * @param userName
     * @param orgName
     * @param roleType
     * @return boolean
     * @throws Exception 
     */
	public static boolean unset_org_role(HttpSession session, String userName,
			String orgName, String roleType) throws Exception {
		String userId;
		String orgId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/organizations/" + orgId + "/" + roleMap.get(roleType)
					+ "/" + userId;
		   CloudFoundryClientUtil.doCCDelete(urlPath, null, session);
		} catch (Exception e) {
			throw e;
		}
		return true;
	}
	
	/**
     * set roles of the user of the space in a org
     * 
     * @param session
     * @param userName
     * @param orgName
     * @param roleType
     * @return boolean
     * @throws Exception 
     */
	public static boolean set_space_role(HttpSession session, String userName,
			String orgName, String spaceName, String roleType) throws Exception {
		HttpClient httpClient = null;
		HttpPut httpPut = null;
		String userId;
		String orgId;
		String spaceId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		spaceId = get_space_id(session, orgName, spaceName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		if (StringUtil.isEmpty(spaceId)) {
			return false;
		}
		if (!add_into_org(session, userName, orgName)) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/spaces/" + spaceId + "/" + roleMap.get(roleType)
					+ "/" + userId;
			
			httpClient =  new DefaultHttpClient();
			httpPut = new HttpPut(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpPut, session);
			HttpResponse response = httpClient.execute(httpPut);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				HttpEntity entity = response.getEntity();  
				String content = EntityUtils.toString(entity, "UTF-8"); 
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			} 
		} catch (Exception e) {
			throw e;
		} finally {
			httpPut.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		
		return true;
	}
	
	/**
     * unset roles of the user of the space in a org
     * 
     * @param session
     * @param userName
     * @param orgName
     * @param roleType
     * @return boolean
     * @throws Exception 
     */
	public static boolean unset_space_role(HttpSession session, String userName,
			String orgName, String spaceName, String roleType) throws Exception {
		String userId;
		String orgId;
		String spaceId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		spaceId = get_space_id(session, orgName, spaceName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		if (StringUtil.isEmpty(spaceId)) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/spaces/" + spaceId + "/" + roleMap.get(roleType)
					+ "/" + userId;
			CloudFoundryClientUtil.doCCDelete(urlPath, null, session);
		} catch (Exception e) {
			throw e;
		}
		
		return true;
	}
	
	/**
     * add a user into org
     * 
     * @param session
     * @param userName
     * @param orgName
     * @return boolean
     * @throws Exception 
     */
	private static boolean add_into_org(HttpSession session, String userName, String orgName) throws Exception {
		HttpClient httpClient = null;
		HttpPut httpPut = null;
		String userId;
		String orgId;
		userId = get_user_id(session, userName);
		orgId = get_org_id(session, orgName);
		if (userId.isEmpty()) {
			return false;
		}
		if (orgId.isEmpty()) {
			return false;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			String urlPath = host + "/v2/organizations/" + orgId + "/users/" + userId;		
			httpClient =  new DefaultHttpClient();
			httpPut = new HttpPut(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpPut, session);
			HttpResponse response = httpClient.execute(httpPut);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				HttpEntity entity = response.getEntity();  
				String content = EntityUtils.toString(entity, "UTF-8"); 
				Map<String, Object> data = JsonUtil.convertJsonToMap(content);
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			} 
		} catch (Exception e) {
			throw e;
		} finally {
			httpPut.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		return true;
	}
	
	/**
     * get id of a user
     * 
     * @param session
     * @param userName
     * @return userId
     * @throws Exception 
     */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String get_user_id(HttpSession session, String userName) throws Exception {
		HttpClient httpClient = null;
		HttpGet httpGet = null;
		String userId = null;
		String urlPath = null;
		if (userName.equals((String) session.getAttribute(LoginHandler.USERNAME))) {
			Object object=session.getAttribute(LoginHandler.USERID);
			if(object!=null){
				userId=(String) object;
			}
			
		}
		if(userId!=null){
			return userId;
		}
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			urlPath = "http://uaa" + host.substring(10) + "/Users?attributes=id,userName&filter=userName+Eq+%22"
					+ userName + "%22";
			//System.out.println(urlPath);
			httpClient =  new DefaultHttpClient();
			httpGet = new HttpGet(urlPath);
			CloudFoundryClientUtil.setUuaHeaders(httpGet, session);
			HttpResponse response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();  
			String content = EntityUtils.toString(entity, "UTF-8");
			Map<String, Object> data = JsonUtil.convertJsonToMap(content);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				throw new CloudFoundryApiException(Integer.valueOf(response.getStatusLine().getStatusCode()), (String) data.get("message"));
			}	
			if((int) data.get("totalResults") == 0) {
				return "";
			}
			userId = (String) ((Map<String, Object>) ((List) (data.get("resources"))).get(0)).get("id");
		} catch (Exception e) {
			throw e;
		} finally {
	        httpGet.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		return userId;
	}
	
	/**
     * get id of a org
     * 
     * @param session
     * @param orgName
     * @return userId
     * @throws Exception 
     */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String get_org_id(HttpSession session, String orgName) throws Exception {
		HttpClient httpClient = null;
		HttpGet httpGet = null;
		String orgId;
		String urlPath = null;
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			urlPath = host + "/v2/organizations?q=name%3A" + orgName 
					+ "&inline-relations-depth=1";
			
			httpClient =  new DefaultHttpClient();
			httpGet = new HttpGet(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpGet, session);
			HttpResponse response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();  
			String content = EntityUtils.toString(entity, "UTF-8"); 
			Map<String, Object> data = JsonUtil.convertJsonToMap(content);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			}
			//System.out.println(((Map<String, Object>)((Map<String, Object>)((List)data.get("resources")).get(0)).get("metadata")).get("guid"));
			if((int) data.get("total_results") == 0) {
				return "";
			}
			orgId = (String) ((Map<String, Object>) ((Map<String, Object>) ((List) data.get("resources")).get(0)).get("metadata")).get("guid");
		} catch (Exception e) {
			throw e;
		} finally {
	        httpGet.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		return orgId;
	}
	
	/**
     * get id of a space
     * 
     * @param session
     * @param orgName
     * @param spaceName
     * @return userId
     * @throws Exception 
     */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static String get_space_id(HttpSession session, String orgName, String spaceName) throws Exception {
		HttpClient httpClient = null;
		HttpGet httpGet = null;
		String orgId = get_org_id(session, orgName);
		if(StringUtil.isEmpty(orgId)){
			return "";
		}
		String spaceId;
		String urlPath = null;
		try {
			String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
			urlPath = host + "/v2/organizations/" + orgId
					+ "/spaces?q=name%3A" + spaceName + "&inline-relations-depth=1";
			
			httpClient =  new DefaultHttpClient();
			httpGet = new HttpGet(urlPath);
			CloudFoundryClientUtil.setAccessHeaders(httpGet, session);
			/**
			 * excute
			 */
			HttpResponse response = httpClient.execute(httpGet);
			HttpEntity entity = response.getEntity();  
			String content = EntityUtils.toString(entity, "UTF-8"); 
			Map<String, Object> data = JsonUtil.convertJsonToMap(content);
			if (!HttpStatusUtil.isSuccessStatus(response.getStatusLine().getStatusCode())) {
				throw new CloudFoundryApiException((Integer) data.get("code"), (String) data.get("description"));
			}
			if((int) data.get("total_results") == 0) {
				return "";
			}
			spaceId = (String) ((Map<String, Object>) ((Map<String, Object>) ((List) data.get("resources")).get(0)).get("metadata")).get("guid");
		} catch (Exception e) {
			throw e;
		} finally {
	        httpGet.abort(); 
	        httpClient.getConnectionManager().shutdown();
		}
		return spaceId;
	}
	
	public static void updateUserPassword(HttpSession session,String uid,Map<String, Object> params) throws Exception{
		String host = ((URL) session.getAttribute(LoginHandler.TARGET)).toString();
		String url = "http://uaa" + host.substring(10) +"/Users/"+uid+"/password";
		CloudFoundryClientUtil.doUaaPut(url, params, session);
	}
	
	public static void main(String[] args){
		Map<String, Object> object=new HashMap<>();
		object.put("password", "123");
		object.put("oldPassword", "12345");		
//		List<String> schemas=new ArrayList<>();
//		schemas.add("urn:scim:schemas:core:1.0");
		//object.put("schemas", schemas);
		try {
			updateUserPassword(null, "02cf91c3-fce7-441e-a410-6aef5d7e6a55", object);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}
